<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <title>Mouse Shadow</title>
</head>

<body>

  <div class="hero">
    <h1 contenteditable>🔥WOAH!</h1>
  </div>

  <style>
    html {
      color: black;
      font-family: sans-serif;
    }

    body {
      margin: 0;
    }

    .hero {
      min-height: 100vh;
      display: flex;
      justify-content: center;
      align-items: center;
      color: black;
    }

    h1 {
      text-shadow: 10px 10px 0 rgba(0, 0, 0, 1);
      font-size: 100px;
    }
  </style>

  <script>
    const hero = document.querySelector('.hero');
    const text = document.querySelector('.hero h1');
    const factor = 0.4; // 阴影和文字的距离比

    function shadowMove(e) {
      // 获取hero在窗口中的位置
      const { offsetWidth: width, offsetHeight: height } = hero;
      // 获取鼠标的位置
      let { offsetX: x, offsetY: y } = e;

      // 鼠标滑动至文字(子元素)上时会掉帧, 需要添加offsetLeft
      if (this !== e.target) {
        x = x + e.target.offsetLeft;
        y = y + e.target.offsetTop;
      }
      
      // 鼠标距离hero中心的位置, 乘上比例
      const xWalk = parseInt((x - width / 2) * factor);
      const yWalk = parseInt((y - height / 2) * factor);

      text.style.textShadow = `
        ${xWalk}px ${yWalk}px 0 rgba(255,0,255,0.7),
        ${xWalk * -1}px ${yWalk}px 0 rgba(0,255,255,0.7),
        ${yWalk}px ${xWalk * -1}px 0 rgba(0,255,0,0.7),
        ${yWalk * -1}px ${xWalk}px 0 rgba(0,0,255,0.7)
      `;
    }

    hero.addEventListener('mousemove', shadowMove)
  </script>
</body>

</html>